<?php

/**
 * Maikuro CMS
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2010, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

/**
 * @see Autoloader
 */
require_once 'Autoloader.php';

/**
 * @see SessionUser
 */
require_once 'SessionUser.php';

abstract class AbstractApplicationContext
{
    /**
     * The base path of the application.
     *
     * @var string
     */
    private $basePath;

    /**
     * The event handler
     *
     * @var EventHandler
     */
    protected $eventHandler;

    /**
     * The mail handler
     *
     * @var IMailHandler
     */
    protected $mailHandler;

    /**
     * Any loaded plugins
     *
     * @var array
     */
    //protected $plugins = array();

    /**
     * The request
     *
     * @var Request
     */
    protected $request;

    /**
     * The response
     *
     * @var Response
     */
    protected $response;

    /**
     *
     * @var ServiceFactory
     */
    protected $serviceFactory;
    
    public function __construct(
        $basePath,
        EventHandler $eventHandler,
        Request $request,
        Response $response,
        ServiceFactory $serviceFactory)
    {
        $this->basePath     = $basePath;
        $this->eventHandler = $eventHandler;
        $this->request      = $request;
        $this->response     = $response;
        $this->serviceFactory = $serviceFactory;

        $this->init();
    }

    public function checkAuthentication()
    {
        // Fixme: frontend won't work with this...
        if (!Auth::isAuthenticated()) {
            if (Auth::hasIdentity()) {
                View::getMessenger()
                    ->addMessage('Your session has timed out. Please login again.', Messenger::WARNING);
            }
            $this->getRequest()->redirectTo('login');
        }
    }

    public function checkPermission($subject, $accessLevel, $subjectId = null)
    {
        $this->checkAuthentication();

        if (!$this->getSessionUser()->hasPermission($subject, $accessLevel, $subjectId)) {
            if (Auth::isAuthenticated()) {
                $this->getRequest()->redirectTo('unauthorized');
            }
        }
    }

    public function checkSitePermission($subject, $accessLevel, $subjectId = null, $siteId = null)
    {
        $this->checkAuthentication();

        if ($siteId == null) {
            $siteId = $this->getCurrentSite()->id;
        }
        if (!$this->getSessionUser()->hasPermission($subject, $accessLevel, $subjectId, $siteId)) {
            if (Auth::isAuthenticated()) {
                $this->getRequest()->redirectTo('unauthorized');
            }
        }
    }

    /**
     *
     * @return AbstractApplicationContext
     */
    public function clearSessionUser()
    {
        Session::set(Constants::SESSION_USER, null);
        return $this;
    }

    /**
     * Returns the base path of the application.
     *
     * @return string
     */
    public function getBasePath()
    {
        return $this->basePath;
    }

    /**
     * Returns the current site.
     *
     * @return SiteEntity
     */
    public abstract function getCurrentSite();

    /**
     * Returns the event handler.
     *
     * @return EventHandler
     */
    public function getEventHandler()
    {
        return $this->eventHandler;
    }

    /**
     *
     * @return MailHandler
     */
    public function getMailHandler()
    {
        return $this->mailHandler;
    }

    /**
     * Returns the plugin with name $name (if any).
     *
     * @todo rename to getActivePlugin???
     * @param string $name
     * @return IPlugin
     * /
    public function getPlugin($name)
    {
        return isset($this->plugins[$name]) ? $this->plugins[$name] : null;
    }
     * 
     */

    /**
     *
     * @return Request
     */
    public function getPreviousRequest()
    {
        return Session::get(Constants::SESSION_PREVIOUS_REQUEST);
    }


    /**
     *
     * @param string $fallBack
     * @return string
     */
    public function getPreviousRequestUri($fallBack = '/')
    {
        $previousRequest = $this->getPreviousRequest();
        if ($previousRequest == null) {
            return $this->getRequest()->getApplicationPath() . $fallBack;
        }
        return $previousRequest->getUri();
    }


    /**
     * Returns the request.
     *
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Returns the response.
     *
     * @return Response
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * Returns the session user.
     *
     * @return SessionUser
     */
    public abstract function getSessionUser();


    /**
     * Initializes the application context.
     */
    protected function init()
    {
        $this->response->setContentType('text/html; charset=utf-8');
        //$this->loadPlugins();
    }

    //abstract protected function loadPlugins();

    /**
     * Sets the session user.
     *
     * @param SessionUser $sessionUser
     * @return AbstractApplicationContext
     */
    public function setSessionUser(SessionUser $sessionUser)
    {
        Session::set(Constants::SESSION_USER, $sessionUser);
        return $this;
    }
}
